package com.rzx.mybackend.service.Impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rzx.mybackend.annotation.OrderIdempotent;
import com.rzx.mybackend.dto.BuyMerchandiseDTO;
import com.rzx.mybackend.entity.BuyMerchandise;
import com.rzx.mybackend.entity.Merchandise;
import com.rzx.mybackend.enums.MerchandiseOrderStatus;
import com.rzx.mybackend.mapper.BuyMerchandiseMapper;
import com.rzx.mybackend.service.BuyMerchandiseService;
import com.rzx.mybackend.service.MerchandiseService;
import com.rzx.mybackend.utils.DynamicTaskUtil;
import com.rzx.mybackend.utils.CommonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * BuyMerchandiseServiceImpl
 *
 * @author renzhexian
 * @date 2025/8/14
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class BuyMerchandiseServiceImpl extends ServiceImpl<BuyMerchandiseMapper, BuyMerchandise> implements BuyMerchandiseService {

    private final MerchandiseService merchandiseService;

    private final CommonUtils commonUtils;

    private final DynamicTaskUtil dynamicTaskManager;

    /**
     * 购买商品
     *
     * @param buyMerchandiseDTOList
     *
     * 订单生成幂等校验
     * 分布式锁对库存扣减校验
     *
     */
    @Transactional
    @OrderIdempotent
    @Override
    public void saveWithValidation(List<BuyMerchandiseDTO> buyMerchandiseDTOList){

        log.info("开始处理订单，商品数量: {}", buyMerchandiseDTOList.size());

        // 按商品ID分组处理
        Map<Long, List<BuyMerchandiseDTO>> groupByMerchandise = buyMerchandiseDTOList.stream()
                .collect(Collectors.groupingBy(BuyMerchandiseDTO::getMerchandiseId));

            // 对每个商品ID分别加锁处理
            for (Map.Entry<Long, List<BuyMerchandiseDTO>> entry : groupByMerchandise.entrySet()) {
                Long merchandiseId = entry.getKey();
                List<BuyMerchandiseDTO> dtoList = entry.getValue();
                log.info("处理商品ID: {}, 数量: {}", merchandiseId, dtoList.size());

                // 按商品ID加锁
                RLock lock = commonUtils.generateStockRedisRLock(merchandiseId);

                boolean isLocked = false;
                try {
                    isLocked = lock.tryLock(5, 10, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
                if (!isLocked) {
                    throw new RuntimeException("商品" + merchandiseId + "库存处理繁忙，请稍后重试");
                }

                try {
                    // 处理该商品的所有购买请求
                    processMerchandiseStock(dtoList, merchandiseId);
                    log.info("商品ID {} 处理完成", merchandiseId);
                    }finally {
                        // 判断当前线程是否持有锁
                        if (lock.isHeldByCurrentThread()) {
                            lock.unlock();
                        }
                    }
            }


        // todo:扣减库存后逻辑

        // 构建订单并保存
        List<BuyMerchandise> buyMerchandises = new ArrayList<>();
        buyMerchandiseDTOList.forEach(buyMerchandiseDTO -> {
            BuyMerchandise buyMerchandise = new BuyMerchandise();
            buyMerchandise.setOrderCode(UUID.randomUUID().toString());
            buyMerchandise.setUserId(commonUtils.getCurrentUserId());
            buyMerchandise.setBuyTime(commonUtils.getCurrentTime());
            buyMerchandise.setMerchandiseId(buyMerchandiseDTO.getMerchandiseId());
            buyMerchandise.setMerchandise_num(buyMerchandiseDTO.getBuyQuantity());
            buyMerchandise.setOrderStatus(MerchandiseOrderStatus.UNPAID.getCode());
            buyMerchandises.add(buyMerchandise);
        });
        saveBatch(buyMerchandises);

        // todo:发布订单后逻辑

        // 定时处理超时订单
        commonUtils.sendOrderExpireMessage(buyMerchandises, 30 * 1000L);
    }


    private void processMerchandiseStock(List<BuyMerchandiseDTO> dtoList, Long merchandiseId) {
        // 获取商品总需求数量
        int totalQuantity = dtoList.stream()
                .mapToInt(BuyMerchandiseDTO::getBuyQuantity)
                .sum();

        Merchandise merchandise = merchandiseService.getById(merchandiseId);
        if (merchandise == null) {
            throw new RuntimeException("商品不存在");
        }
        if (merchandise.getMerchandiseStock() < totalQuantity) {
            throw new RuntimeException("商品库存不足");
        }


        // 批量扣减库存
        merchandiseService.releaseStock(merchandiseId, totalQuantity);
    }


    @Transactional
    @Override
    public void cancelOrder(List<Long> orderIds) {
        removeBatchByIds(orderIds);
    }

}
